/*
 *  Howl.cpp
 *  SoundController0002
 *
 *  Created by jiro on 11/06/17.
 *  Copyright 2011 jiro music. All rights reserved.
 *
 */

#include "Howl.h"

#include "../../sc/Common/WellTemperament.h"
#include <sstream>

namespace sc
{
namespace hs
{

	Howl::Howl()
	{}

	Howl::Howl( Sound::WaveType waveType1, Sound::WaveType waveType2,
				::sc::Note::MidiNumber midiNumber1, ::sc::Note::MidiNumber midiNumber2,
				double nthHarmonics1, double nthHarmonics2 )
	{
		sounds[ 0 ] = HarmonicSound( waveType1, midiNumber1, nthHarmonics1 );
		sounds[ 1 ] = HarmonicSound( waveType2, midiNumber2, nthHarmonics2 );
	}

	Howl::Howl( Sound::WaveType waveType1, Sound::WaveType waveType2,
		  ::sc::Note::MidiNumber midiNumber1, ::sc::Note::MidiNumber midiNumber2,
		  double nthHarmonics1, double nthHarmonics2,
		  double dynamics1, double dynamics2 )
	{
		sounds[ 0 ] = HarmonicSound( waveType1, midiNumber1, nthHarmonics1, dynamics1 );
		sounds[ 1 ] = HarmonicSound( waveType2, midiNumber2, nthHarmonics2, dynamics2 );
	}

	Howl::Howl( double frequency1, double frequency2, double dynamics1, double dynamics2 )
	{
		double nthOfHarmonics = 1.0;
		sounds[ 0 ] = HarmonicSound( frequency1, nthOfHarmonics, dynamics1 ); 
		sounds[ 1 ] = HarmonicSound( frequency2, nthOfHarmonics, dynamics2 ); 
	}

	const HarmonicSound& Howl::GetHarmonicSound( int index  ) const
	{
		return sounds[ index ];
	}

	double Howl::GetFrequency() const
	{
		double freq0 = sounds[ 0 ].GetNthOfHarmonic() * WellTemperament::GetFrequency( sounds[ 0 ].GetMidiNumber() );
		double freq1 = sounds[ 1 ].GetNthOfHarmonic() * WellTemperament::GetFrequency( sounds[ 1 ].GetMidiNumber() );
		return fabs( freq0 - freq1 );
	}
	
	double Howl::GetDuration() const
	{
		return 1.0 / GetFrequency();
	}

	double Howl::GetDynamics() const
	{
		double dynamics = sounds[ 0 ].GetDynamics() + sounds[ 1 ].GetDynamics();
		return dynamics;
	}

	Sound::WaveType Howl::GetWaveType( int index ) const
	{
		return sounds[ index ].GetWaveType();
	}

	::sc::Note::MidiNumber Howl::GetNoteMidiNumber( int index  ) const
	{
		return sounds[ index ].GetMidiNumber();
	}

	int Howl::GetNthHarmonics( int index  ) const
	{
		return sounds[ index ].GetNthOfHarmonic();
	}

	double Howl::GetWeight() const
	{
		double weight0 = sounds[ 0 ].GetHarmonicWeight( sounds[ 0 ].GetNthOfHarmonic() );
		double weight1 = sounds[ 1 ].GetHarmonicWeight( sounds[ 1 ].GetNthOfHarmonic() );
		return weight0 * weight1;
	}

	bool Howl::operator < ( const Howl& howl ) const
	{
		if ( GetWeight() > howl.GetWeight() )
		{
			return true;
		}
		return false;
	}

	bool Howl::operator == ( const Howl& howl ) const
	{
		if ( ( ( sounds[ 0 ] == howl.sounds[ 0 ] ) and ( sounds[ 1 ] == howl.sounds[ 1 ] ) ) or
			 ( ( sounds[ 0 ] == howl.sounds[ 1 ] ) and ( sounds[ 1 ] == howl.sounds[ 0 ] ) ) )
		{
			return true;
		}
		return false;
	}

	bool Howl::operator != ( const Howl& howl ) const
	{
		return not ( *this == howl );
	}

	std::string Howl::ToString( int tabCount ) const
	{
		std::stringstream ss;
		std::string tabs;
		for ( int i = 0; i < tabCount; i++ )
		{
			tabs.append( "\t" );
		}

		ss  << tabs << "Howl:\n";
		tabs.append( "\t" );
		ss  << tabs << "frequency: " << GetFrequency() << "\n"
			<< tabs << "weight: " << GetWeight() << "\n"
			<< tabs << sounds[ 0 ].ToString() << "\n"
			<< tabs << sounds[ 1 ].ToString();

		return ss.str();
	}

}
}
